#!/usr/bin/env python2.4
# -*- coding: utf8 -*-

import sys
import os
import soya
import soya.sphere
import soya.cube
import soya.sdlconst
import math
import soya.pudding as pudding

from soccerbots.core.structs import *

class PlayGround(soya.Body):
    '''
        PlayGround Body
    '''
    def __init__(self, scene):
        soya.path.append('soccerbots/gui/data')

        ''' Inits a new PlayGround body element. '''
        material = soya.Material()
        material.texture = soya.Image.get('ground.png')
        world = soya.World()
        grass_w = 1250
        grass_h = 900
        grass = soya.Face(world, [soya.Vertex(world, -grass_w, grass_h, 0, 0, 0),
                                  soya.Vertex(world, grass_w, grass_h, 0, 1, 0),
                                  soya.Vertex(world, grass_w, -grass_h, 0, 1, 0.72),
                                  soya.Vertex(world, -grass_w, -grass_h, 0, 0, 0.72),
                                 ], material)
        grass.double_sided = 1
        soya.Body.__init__(self, scene, world.to_model())

class WhiteBall(soya.Body):
    def __init__(self, scene):
        world = soya.sphere.Sphere()
        soya.Body.__init__(self, scene, world.to_model())

        material = soya.Material()
        material.environment_mapping = 1 # Specifies environment mapping is active
        material.texture = soya.Image.get("ball1.png")# The textured sphere map
        
        for face in world.children:
            face.smooth_lit = 1
        
        # Donar volum a l'esfera
        self.scale(21.35,21.35,21.35)
        self.x = 0
        self.y = 0
        self.z = 21.35
        
    def SetXY(self, x, y):
        self.x = x
        self.y = y


class Robot(soya.Body):
    def __init__(self, name, scene, w, team):
        self.name = name
        self.w = w
        self.camera = soya.Camera(scene)
        self.camera.back = 3000 # Crop limit
        self.inicialitzat = False
    
        material = []
        if team==1:
            material.append(soya.Material(soya.Image.get("red_cap0.png")))
            material.append(soya.Material(soya.Image.get("red_kk.png")))
        else:
            material.append(soya.Material(soya.Image.get("blue_cap0.png")))
            material.append(soya.Material(soya.Image.get("blue_kk.png")))
        
        
        world=soya.cube.Cube()
        i = 0
        for face in world.children:
        #   face.smooth_lit=1
            if ( i == 0 ):
                face.material=material[0]
            else:
                face.material=material[1]
            i += 1          
            
        #self.cube = soya.Body(scene, cube_world.to_model())
        soya.Body.__init__(self, scene, world.to_model())
        
        self.scale(75,75,75)
        self.x = 100
        self.y = 100
        self.z = 37.5 #160
        self.alpha = 0
        self.camera.set_xyz(self.x , self.y, self.z)
        pos = soya.Point()
        
        pos.x = self.x + 1
        pos.y = self.y 
        pos.z = self.z
        
        self.camera.look_at(pos)
        self.camera.rotate_x(90)

    def SetXY(self, x, y):
        self.x = x
        self.y = y
        self.camera.set_xyz(self.x, self.y, self.z)
        
    def SetAngle(self, alpha):
        #en graus 
        self.rotate_z(alpha - self.alpha)
        self.camera.rotate_z(alpha - self.alpha)
        self.alpha = alpha  
        
        
    def ActivateCamera(self):
        #vista de la camera
        #soya.set_root_widget(self.camera)
        self.w.cameras = []
        self.w.add_child(self.camera)
        #current_camera = self.camera
        
class MenuOption(pudding.control.Label):
    def __init__(self, label, function):
        pudding.control.Label.__init__(self, label = label, height = 190, width = 190)
        #self.set_display_text("en el init..:")
        pudding.control.Label.set_display_text(self, 'la label')
        self.function = function

        self.color1 = (0., 1., 1., 1.)
        self.color2 = (1., 0., 0., 1.)
        self.color = self.color1
        #self.resize(.1, .1, .9, 90)
        
        #print "Available fonts are :", pudding.sysfont.get_fonts()
        #myfont = soya.Font(pudding.sysfont.SysFont('serif, freeserif'), 30, 30 )
        #print "Choosen font :", myfont
        #self.font = myfont
                
    def on_focus(self):
        self.color = self.color2
        self.update()
        
    def on_loose_focus(self):
        self.color = self.color1

    def on_mouse_up(self, button, x, y):
        self.function()
        return True

class GButton(pudding.control.Button):
    def __init__(self, label, function):
        pudding.control.Button.__init__(self, label = label)
        self.function = function
        
    def on_click(self):
        self.function()
    
    def on_focus(self):
        self.background_color = (0., 0., 0., 0.9)
        
    def on_loose_focus(self):
        self.background_color = (0., 0., 0., 0.3)
        

class GImage(pudding.control.Image,pudding.control.Button):
    def __init__(self, w, mypic, left, top, function, team, player):
        pudding.control.Button.__init__(self, label = '')
        pudding.control.Image.__init__(self, w, mypic, left = left, top = top, width = 32, height=32)
        
        self.function = function
        self.team = team
        self.player = player
        
    def on_click(self):
        self.function(self.team, self.player)


class GuiImpl(soya.Body):
    def __init__(self, geometry=(500,400), fullscreen=0):
        soya.init("SoccerBOTS",width=geometry[0],height=geometry[1],fullscreen=fullscreen)
        soya.path.append(os.path.join(os.path.dirname(sys.argv[0]), "data"))
        
        pudding.init()
        self.rootw = pudding.core.RootWidget(width = geometry[0]/9,height = geometry[1])
        
        # Creates the scene.
        self.scene = soya.World()
        soya.Body.__init__(self, self.scene, None)
        
        # Set up an atmosphere
        self.scene.atmosphere = soya.Atmosphere()
        self.scene.atmosphere.bg_color = (1,0,1, 1.0)
        
        # Play ground
        self.ground = PlayGround(self.scene)

        # Creem botons principals
        self.inici_button = MenuOption('Inici', self.inici)
        self.falta_button = MenuOption('Falta', self.showFaults)
        self.gol_button = MenuOption('Gol', self.goalFunc)
        self.quit_button = MenuOption('Sortir', self.quit)
        self.penalty_button = MenuOption('Penalty', self.penalty)
        self.freekick_button = MenuOption('Free Kick', self.freekick)
        self.freeball_button = MenuOption('Free Ball', self.freeball)
        self.teama_button = MenuOption('TeamA', self.goTeamA)
        self.teamb_button = MenuOption('TeamB', self.goTeamB)

        # Creem contenidor principal
        self.vcont = pudding.container.VerticalContainer(self.rootw)
        self.vcont.right = 20
        self.vcont.top = 10
        self.vcont.anchors = pudding.ANCHOR_RIGHT
        self.vcont.padding = 5
        self.vcont.visible = True
        self.vcont.add_child(self.inici_button, pudding.CENTER_HORIZ)
        self.vcont.add_child(self.falta_button, pudding.CENTER_HORIZ)
        self.vcont.add_child(self.gol_button, pudding.CENTER_HORIZ)
        self.vcont.add_child(self.quit_button, pudding.CENTER_HORIZ)

        self.inici_button.visible = False
        self.falta_button.visible = False
        self.gol_button.visible = False

        # Creem contenidor de faltes
        self.mFaults = pudding.container.VerticalContainer(self.rootw, width = 200, height = 200)
        self.mFaults.right = 20
        self.mFaults.top = 150
        self.mFaults.anchors = pudding.ANCHOR_RIGHT
        self.mFaults.padding = 5
        self.mFaults.visible = False
        self.mFaults.add_child(self.penalty_button, pudding.CENTER_HORIZ)
        self.mFaults.add_child(self.freekick_button, pudding.CENTER_HORIZ)
        self.mFaults.add_child(self.freeball_button, pudding.CENTER_HORIZ)
        
        # Creem el contenidor d'equips
        self.mTeams = pudding.container.VerticalContainer(self.rootw, width = 200, height = 200)
        self.mTeams.right = 20
        self.mTeams.top = 150
        self.mTeams.anchors = pudding.ANCHOR_RIGHT
        self.mTeams.padding = 5
        self.mTeams.visible = False
        self.mTeams.add_child(self.teama_button, pudding.CENTER_HORIZ)
        self.mTeams.add_child(self.teamb_button, pudding.CENTER_HORIZ)

        # Creem el marcador
        self.Marcador = pudding.control.Label(label = 'Local  0 - 0  Visitant')
        c = pudding.container.HorizontalContainer(self.rootw, left=10, top=10, width=300, height=200)
        c.add_child(self.Marcador)
        
        # Camera
        self.camera = soya.Camera(self.scene)
        self.camera.set_xyz(0, -1000, 2000)
        self.camera.back = 3000 # Crop limit
        self.camera.look_at(self.ground)
        
        # Robots
        self.robots = {}
        self.robots["equipA"] = {}
        self.robots["equipB"] = {}
    
        # Adds a camera and a light 
        light = soya.Light(self.scene)
        light.set_xyz(0, 0, 1000)
        
        # imatges de les cameres en primera persona
        cams = []
        mypic = soya.Material( soya.Image.get('cam32.png'))
        middle = (geometry[0]-30)/2
        height = geometry[1]
        teams = ['equipA','equipB']
        side = [-1, 1]
        h = height-40
        for i in range(2):
            m = middle + 40*side[i]
            for key in TeamState.keyset:
                m += 40*side[i]
                img = GImage(self.rootw, mypic ,m, h, self.clickImg, teams[i], key)
                cams.append(img)
        # logo app        
        logo = pudding.control.Logo(self.rootw, 'logo.png')
        
        self.rootw.add_child(self.camera)
        soya.set_root_widget(self.rootw)

    def begin_round(self):
        soya.Body.begin_round(self)
        for event in soya.MAIN_LOOP.events:
            if event[0] == soya.sdlconst.KEYDOWN:
                if event[1] == soya.sdlconst.K_q:
                    soya.MAIN_LOOP.stop()
                elif event[1] == soya.sdlconst.K_c: 
                    self.camera.set_xyz(0, -1000, 2000)
                    self.camera.look_at(self.ground)
                    self.rootw.cameras = []
                    self.rootw.add_child(self.camera)
            elif event[0] == soya.sdlconst.QUIT:
                soya.MAIN_LOOP.stop()

    def render(self):
        soya.render()

    def clickImg(self, team, player):
        try:
            self.robots[team][player].ActivateCamera()
        except:
            pass
    
    def inici(self):
        self.inici_button.visible = False

        e = GUIEvent()
        e.type = GUIEvent.INICI
        self.CallBackFunction(e)

    def goalFunc(self):
        e = GUIEvent()
        e.type = GUIEvent.GOAL
        self.CallBackFunction(e)
        
    def showFaults(self):
        self.mFaults.visible = True

    def quit(self):
        soya.MAIN_LOOP.stop()
        #sys.exit(0)

    def FaultFunc(self, TipusFalta, Equip):
        e = GUIEvent()
        e.type = GUIEvent.FAULT
        e.fault = TipusFalta
        e.team = Equip
        self.CallBackFunction(e)
        
    def goTeamA(self):     
        self.FaultFunc(self.TipusFalta, GUIEvent.TEAM_A)
        self.mFaults.visible = False
        self.mTeams.visible = False
    
    def goTeamB(self):     
        self.FaultFunc(self.TipusFalta, GUIEvent.TEAM_B)
        self.mFaults.visible = False
        self.mTeams.visible = False
                
    def penalty(self):
        self.TipusFalta = GUIEvent.PENALTY
        self.mFaults.visible = False
        self.mTeams.visible = True
    
    def freekick(self):
        self.TipusFalta = GUIEvent.FREE_KICK
        self.mFaults.visible = False
        self.mTeams.visible = True
    
    def freeball(self):
        self.TipusFalta = GUIEvent.FREE_BALL
        self.mFaults.visible = False
        self.mTeams.visible = True
   
    def setPlayers(self, team):
        if team==1:
            color_a = 1
            color_b = 2
        else:
            color_a = 2
            color_b = 1

        self.robots["equipA"]["goalkeeper"] = Robot("GoalKeeper", self.scene, self.rootw, color_a)
        self.robots["equipA"]["player1"] = Robot("Player1", self.scene, self.rootw, color_a)
        self.robots["equipA"]["player2"] = Robot("Player2", self.scene, self.rootw, color_a)
        self.robots["equipA"]["player3"] = Robot("Player3", self.scene, self.rootw, color_a)
        self.robots["equipA"]["player4"] = Robot("Player4", self.scene, self.rootw, color_a)
        self.robots["equipB"]["goalkeeper"] = Robot("GoalKeeper", self.scene, self.rootw, color_b)
        self.robots["equipB"]["player1"] = Robot("Player1", self.scene, self.rootw, color_b)
        self.robots["equipB"]["player2"] = Robot("Player2", self.scene, self.rootw, color_b)
        self.robots["equipB"]["player3"] = Robot("Player3", self.scene, self.rootw, color_b)
        self.robots["equipB"]["player4"] = Robot("Player4", self.scene, self.rootw, color_b)
        self.ball = WhiteBall(self.scene)

        self.inici_button.visible = True
        

    def loop(self): 
        pudding.main_loop.MainLoop(self.scene).main_loop()
        self.SetScoring(0,0)
    
    def translatePosition(self, pos):
        return (pos[0], pos[1]-900)

    def SetState(self, state, start=True):
        if start:
            self.inici_button.visible = False
            self.falta_button.visible = True
            self.gol_button.visible = True
        else:
            self.inici_button.visible = True
            self.falta_button.visible = False
            self.gol_button.visible = False

        #posicio de la pilota
        r = self.translatePosition(state.ball.position)
        self.ball.SetXY(r[0], r[1])
        
        #posicio i direccio del primer equip
        for k in TeamState.keyset:
            r = self.translatePosition(state.teamA[k].position)
            self.robots["equipA"][k].SetXY(r[0], r[1])      
            self.robots["equipA"][k].SetAngle(state.teamA[k].direction)
            
        #posicio i direccio del segon equip
        for k in TeamState.keyset:
            r = self.translatePosition(state.teamB[k].position)
            self.robots["equipB"][k].SetXY(r[0], r[1])      
            self.robots["equipB"][k].SetAngle(state.teamB[k].direction)
            
    def SetScoring(self, local, visitant):
        self.Marcador.label = "Local  " + str(local) + " - " + str(visitant) + "  Visitant"

    def SetCallBack(self, function):
        self.CallBackFunction = function
